<?php

namespace app\api\logic;

use app\common\exception\BusinessException;
use app\common\model\User as UserModel;
use app\common\service\MailService;
use app\common\service\SmsService;
use app\common\service\UserService;
use think\captcha\facade\Captcha;
use think\facade\Cache;
use think\facade\Session;
use think\Response;

class Verify
{
    /**
     * 获取图形验证码
     * @param $key
     * @return Response
     * @throws BusinessException
     */
    public function getCode($key): Response
    {
        // 获取验证码
        $captchaResponse = Captcha::create();

        // 提取验证码Hash
        $captchaKey = 'captcha.key';
        $captchaHash = Session::get($captchaKey);
        if (!$captchaHash) {
            throw new BusinessException('获取验证码失败');
        }

        // 保存验证码结果
        $key = "captcha_$key";
        Cache::set($key, $captchaHash, 3600);

        //返回
        return $captchaResponse;
    }

    /**
     * 发送短信验证码
     * @param array $params
     * @throws BusinessException
     */
    public function sendSmsCode(array $params)
    {
        // 提取参数
        $ip = $params['ip'];
        $code = $params['code'];
        $scene = $params['scene'];   // 10. 注册  20.登录  30.绑定  40.找密
        $mobile = trim($params['mobile']);
        $userId = $params['userId'] ?? 0;
        $appId = getAppId();

        // 检查验证码
        if (!$this->checkCode($mobile, $code)) {
            throw new BusinessException('验证码不正确或已失效');
        }

        // 根据场景检查数据
        $userService = new UserService();
        $mobileUser = $userService->getUserByMobile($appId, $mobile);

        // 注册场景校验
        if ($scene == 10 && $mobileUser) {
            throw new BusinessException('当前手机号已注册');
        }

        // 登录场景校验
        if ($scene == 20 && !$mobileUser) {
            throw new BusinessException('当前手机号未注册');
        }

        // 绑定场景校验
        if ($scene == 30) {
            if (!$userId) {
                throw new BusinessException('未获取到您的身份');
            }
            if ($mobileUser) {
                if ($mobileUser['id'] != $userId) {
                    throw new BusinessException('您输入的手机号其他人已绑定');
                } else {
                    throw new BusinessException('您已绑定手机号');
                }
            }
        }

        // 找密场景校验
        if ($scene == 40 && !$mobileUser) {
            throw new BusinessException('当前手机号未注册');
        }

        // 校验IP+MB
        $smsServer = new SmsService();
        $smsServer->check($mobile, $ip, '');

        // 发送短信
        $verifyCode = rand(100000, 999999);
        $smsServer->sendCode($mobile, $verifyCode, $ip);
    }

    /**
     * 发送邮件验证码
     * @param array $params
     * @throws BusinessException
     */
    public function sendMailCode(array $params)
    {
        //提取参数
        $key = $params['key'];
        $action = $params['action'];
        $userId = $params['userId'] ?? 0;

        //检查userId
        if ($action != 1 && !$userId) {
            throw new BusinessException('登陆状态异常');
        }

        /**
         * action模板绑定
         * action:1 重置密码
         * action:2 绑定邮箱
         * action:3 解绑邮箱
         */
        $action_tpl_dict = [
            '1' => 'tpl.verify.api.S1',
            '2' => 'tpl.verify.api.S2',
            '3' => 'tpl.verify.api.S3',
        ];
        if (!isset($action_tpl_dict[$action])) {
            throw new BusinessException('未配置邮件模板');
        }
        $tpl_id = $action_tpl_dict[$action];

        /*
         * action逻辑检查
         */
        $action_key_check = [
            /**
             * 重置密码
             */
            '1' => function () use (&$key) {
                $field = 'email';
                $where = [['email|username', '=', $key]];
                $user = app(UserModel::class)->field($field)->where($where)->find();
                if (!$user) {
                    throw new BusinessException('未找到对应账户');
                }
                if (!$user['email']) {
                    throw new BusinessException('账户未绑定邮箱');
                }
                $key = $user['email'];
            },
            /**
             * 绑定邮箱
             */
            '2' => function () use ($key, $userId) {
                $email = app(UserModel::class)->where(['id' => $userId])->value('email', '');
                if ($key == $email) {
                    throw new BusinessException('绑定邮箱不得和账号原邮箱一致');
                }
            },
            /**
             * 解绑邮箱
             */
            '3' => function () use ($key, $userId) {
                $email = app(UserModel::class)->where(['id' => $userId])->value('email', '');
                if (!$email) {
                    throw new BusinessException('当前账户未绑定邮箱');
                }
            },
        ];
        if (isset($action_key_check[$action])) {
            ($action_key_check[$action])();
        }

        //发送邮件
        $mailServer = new MailService();
        $mailServer->sendCode($key, $tpl_id);
    }

    /**
     * 校验验证码
     * @param $key
     * @param $code
     * @return bool
     */
    public function checkCode($key, $code): bool
    {
        $key = "captcha_$key";
        $captchaHash = Cache::get($key);
        if ($captchaHash) {
            $code = mb_strtolower($code, 'UTF-8');
            return password_verify($code, $captchaHash);
        }
        return false;
    }
}